import React, { memo } from 'react';
import { message, Table } from 'antd';
import { DndProvider, DragSource, DropTarget } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import styles from './index.less';

let dragingIndex = -1;

class BodyRow extends React.Component {
    render() {
        const { isOver, connectDragSource, connectDropTarget, moveRow, showCursor, ...restProps } = this.props;
        const { children } = restProps;
        const { editFlag } = children?.[0]?.props?.record || {};
        const style = { ...restProps.style, cursor: editFlag && showCursor ? 'move' : 'default' };
        let { className } = restProps;
        if (isOver) {
            if (restProps.index > dragingIndex) {
                className += ' drop-over-downward';
            }
            if (restProps.index < dragingIndex) {
                className += ' drop-over-upward';
            }
        }

        return connectDragSource(connectDropTarget(<tr {...restProps} className={className} style={style} />));
    }
}

const rowTarget = {
    drop(props, monitor) {
        const { index: hoverIndex, hintMessage } = props;
        const dragIndex = monitor.getItem().index;

        // Don't replace items with themselves
        if (dragIndex === hoverIndex) {
            return;
        }

        if (hoverIndex === 0) {
            message.error(hintMessage, 1);
            return;
        }
        props.moveRow(dragIndex, hoverIndex);
        monitor.getItem().index = hoverIndex;
    }
};

const rowSource = {
    beginDrag(props) {
        dragingIndex = props.index;
        return {
            index: props.index
        };
    },
    canDrag(props) {
        const { children, isDrag } = props;
        const { record } = children?.[0]?.props;
        return !!record.editFlag && isDrag;
    }
};

const EditableRow = DropTarget('row', rowTarget, (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver()
}))(
    DragSource('row', rowSource, connect => ({
        connectDragSource: connect.dragSource()
    }))(BodyRow)
);

const HandoverTable = ({ columns, loading, dataSource, setDataSource, showCursor, hintMessage, isDrag }) => {
    const reorder = (list, startIndex, endIndex) => {
        const result = Array.from(list);

        const [removed] = result.splice(startIndex, 1);

        result.splice(endIndex, 0, removed);
        return result;
    };

    const moveRow = (dragIndex, hoverIndex) => {
        const data = reorder(dataSource, dragIndex, hoverIndex);
        setDataSource(data);
    };

    const components = {
        body: {
            row: EditableRow
        }
    };
    return <DndProvider backend={HTML5Backend}>
        <Table
            components={components}
            rowKey={record => record.id}
            className={styles.tableWrap}
            loading={loading}
            dataSource={dataSource}
            columns={columns}
            pagination={false}
            onRow={(record, index) => ({
                index,
                isDrag,
                showCursor,
                hintMessage,
                moveRow
            })}
        />
    </DndProvider>
};
export default memo(HandoverTable);
